//======================================================================================
/** \file virdemo.cpp
 *    This file contains a program to demonstrate how virtual methods, non virtual 
 *    methods, and ordinary functions can be called in AVR-GCC. 
 *
 *  Revisions
 *    \li 02-03-2008 JRR Original file
 *    \li 03-04-2008 JRR Added multiple inheritance tests
 *    \li 05-06-2008 JRR Changed to use new serial port classes
 *    \li 01-29-2009 JRR Changed again to use even newer serial port classes
 *    \li 04-19-2012 JRR Stripped out speed test stuff to make clearer demonstration
 *
 *  License:
 *    This file copyright 2007-2012 by JR Ridgely. It is released under the Lesser GNU
 *    public license, version 2.
 */
//======================================================================================

											// System headers included with < >
#include <stdlib.h>							// Standard C library
#include <avr/io.h>							// Input-output ports, special registers
#include <avr/interrupt.h>					// Interrupt handling functions

											// User written headers included with " "
#include "rs232int.h"						// Serial port header
#include "global_debug.h"					// Global debugging printout macros
#include "virdemo_classes.h"				// Classes containing virtual methods


//--------------------------------------------------------------------------------------
/** The main function is the "entry point" of every C program, the one which runs first
 *  (after standard setup code has finished). For mechatronics programs, main() runs an
 *  infinite loop and never exits. 
 */

int main ()
{
	char input_char;						// Holds a character typed by the user

	// Create a serial port object which should be hooked up to a dumb terminal program 
	// like GTKterm or minicom or PuTTY on a PC
	rs232 the_serial_port (9600, 1);
	sei ();

	// Print a greeting message. 
	the_serial_port << clrscr << "ME405: Inherited Method Demonstration" << endl;

	// Create a child class object. Several pointers will be made to point to it
	child_class child_object (&the_serial_port);

	// Create a pointer of the type that points to the child class and put the address
	// of the child object into that pointer. This is nothing special, as the pointer
	// is already typed to point to a child object, so there's no special difficulty in
	// using it to call methods belonging to the child class
	child_class* p_child_obj = &child_object;

	// Create a pointer of the type that points to the parent class and then put the
	// address of the child object into that pointer
	mom_class* p_mom_obj = &child_object;

	// Run the ordinary function
	the_serial_port << "Running ordinary C function..." << endl;
	just_function ();

	// Run the non-virtual overridden method with a parent class pointer
	the_serial_port << "Ordinary C++ method with parent pointer...";
	p_mom_obj->omethod ();

	// Run the non-virtual overridden method with a child class pointer
	the_serial_port << "Ordinary C++ method with child pointer...";
	p_child_obj->omethod ();

	// Run the virtual method with a pointer to the child class
	the_serial_port << "Virtual C++ method with parent pointer...";
	p_mom_obj->vmethod ();

	// Run the virtual method with a pointer to the child class
	the_serial_port << "Virtual C++ method with child pointer...";
	p_child_obj->vmethod ();

	// Brag about what we've accomplished
	the_serial_port << "Test complete; virtual methods pwned." << endl;

	// Run the main scheduling loop, in which the action to run is done repeatedly.
	// In the future, we'll run tasks here; for now, just do things in a simple loop
	while (true)
	{
		// Check if the user has typed something. If so, either clear the counter to
		// a reading of zero time or write a carriage return and linefeed
		if (the_serial_port.check_for_char ())
		{
			input_char = the_serial_port.getchar ();
			if (input_char == 'c')
				the_serial_port 
				<< "Virtual test program finished and stuck in infinite loop" << endl;
		}
	}

	return (0);
}
